﻿using System;
using System.Collections.Generic;
using Infinity.Common.Logger;
using Infinity.Compilers;
using Infinity.Expressions;
using System.Linq;
using Infinity.Statements.Block;
using System.Text;
using System.Reflection;
using Infinity.Statements;
using Infinity.Statements.Command;
using Infinity.Statements.Condition;
using Infinity.Statements.Declare;
using Infinity.Statements.Loop;
using Infinity.Statements.Program;

namespace Infinity.Statements
{
	/// <summary>
	/// Factory class for creating statements
	/// </summary>
	public interface IStatementFactory
	{
		ILogger Logger { get; set; }
		IExpressionFactory ExpressionFactory { get; set; }

		List<IProgramStatement> SymbolTable { get; set; }

		List<Assembly> AssemblyCollection { get; set; }

		void LoadAssembly(string name);
		void UnloadAssembly(string name);

		IExpressionStatement CreateExpressionStatement(IExpression expression);

		ITypeDeclareStatement CreateTypeDeclareStatement(string name, string typeName);

		ITypeDeclareStatement CreateTypeDeclareStatement(
			string name, string localVariableName, string baseType, IExpression condition);

		void CreateProcedure(
			string name, IList<IParameterDeclareStatement> parameters, IList<IVariableStatement> localVariables,
			IList<IStatement> commands);

		IAssignmentStatement CreateAssignment(IIdentifierExpression left, IExpression right);
		IBlockStatement CreateBlockStatement(params IStatement[] statementList);

		IWhileStatement CreateWhileStatement(IExpression condition, IBlockStatement body);
		IForeachStatement CreateForeachStatement(IIdentifierExpression variable, IExpression array, IBlockStatement body);

		IForStatement CreateForStatement(
			IIdentifierExpression variable, IExpression start, IExpression end, IExpression by, IBlockStatement body);

		IIfStatement CreateIfStatement(
			IExpression condition, IBlockStatement bodyStatement, List<IIfStatement> elseIfStatement,
			IBlockStatement elseStatement);

		IStatement CreateConstraint(IStatement statement, IConstraintStatement constraint);

		IStatement CreateConstraint(
			IStatement statement, IPreConditionStatement preconditionStatement, IPostConditionStatement postconditionStatement,
			IInvariantStatement invariant);

		IConstraintStatement CreateConstraint(
			IExpression preconditionStatement, IExpression postconditionStatement, IExpression invariant,
			bool isStrictPreCondition = false, bool isStrictPostCondition = false, bool isStrictInvariant = false);

		IVariableStatement DeclareVariable(string name, string type, IExpression value, bool isConst);
		IVariableStatement[] CreateVariableDeclarations(params IVariableStatement[] variables);
	}
}